#include "hal_data.h"

FSP_CPP_HEADER
void R_BSP_WarmStart(bsp_warm_start_event_t event);
FSP_CPP_FOOTER


/* 用户头文件包含 */
#include "led/bsp_led.h"
#include "debug_uart/bsp_debug_uart.h"
#include "qspi_flash/bsp_qspi_flash.h"


#define  FLASH_WriteAddress     0x00000
#define  FLASH_ReadAddress      FLASH_WriteAddress
#define  FLASH_SectorToErase    FLASH_WriteAddress

/* 发送缓冲区初始化 */
uint8_t Tx_Buffer[] = "感谢您选用野火启明瑞萨RA开发板";
uint8_t Rx_Buffer[sizeof(Tx_Buffer)];


/*
 * 函数名：Buffercmp
 * 描述  ：比较两个缓冲区中的数据是否相等
 * 输入  ：pBuffer1     src缓冲区指针
 *         pBuffer2     dst缓冲区指针
 *         BufferLength 缓冲区长度
 * 输出  ：无
 * 返回  ：0 pBuffer1 等于   pBuffer2
 *         1 pBuffer1 不等于 pBuffer2
 */
int Buffercmp(uint8_t *pBuffer1, uint8_t *pBuffer2, uint16_t BufferLength)
{
    while (BufferLength--)
    {
        if (*pBuffer1 != *pBuffer2)
        {
            return 1;
        }

        pBuffer1++;
        pBuffer2++;
    }
    return 0;
}

/*******************************************************************************************************************//**
 * main() is generated by the RA Configuration editor and is used to generate threads if an RTOS is used.  This function
 * is called by main() when no RTOS is used.
 **********************************************************************************************************************/
void hal_entry(void)
{
    /* TODO: add your own code here */
    uint32_t FlashID = 0;
    uint32_t FlashDeviceID = 0;

    LED_Init();         // LED 初始化
    Debug_UART4_Init(); // SCI4 UART 调试串口初始化
    QSPI_Flash_Init();  // 串行FLASH初始化

    printf("这是一个串行FLASH的读写例程\r\n");
    printf("打开串口助手查看打印的信息\r\n\r\n");


    /* 获取 SPI g_qspi0_flash ID */
    FlashID = QSPI_Flash_ReadID();
    FlashDeviceID = QSPI_Flash_ReadDeviceID();
    
    if ((FlashID == FLASH_ID_W25Q32JV) || (FlashID == FLASH_ID_AT25SF321B))
    {
        if(FlashID == FLASH_ID_W25Q32JV)
        {
            printf("检测到串行FLASH：W25Q32 !\r\n");
        }
        else
        {
            printf("检测到串行FLASH：AT25SF32 !\r\n");
        }
        printf("FlashID is 0x%X, Manufacturer Device ID is 0x%X.\r\n", FlashID, FlashDeviceID);
        
        
        /* 擦除将要写入的 SPI FLASH 扇区，FLASH写入前要先擦除 */
        // 这里擦除4K，即一个扇区，擦除的最小单位是扇区
        QSPI_Flash_SectorErase(FLASH_SectorToErase);

        /* 将发送缓冲区的数据写到flash中 */
        // 这里写一页，一页的大小为256个字节
        QSPI_Flash_BufferWrite(Tx_Buffer, FLASH_WriteAddress, sizeof(Tx_Buffer));
        printf("写入的数据为：%s \r\n", Tx_Buffer);

        /* 将刚刚写入的数据读出来放到接收缓冲区中 */
        QSPI_Flash_BufferRead(Rx_Buffer, FLASH_ReadAddress, sizeof(Tx_Buffer));
        printf("读出的数据为：%s \r\n", Rx_Buffer);

        if (Buffercmp(Tx_Buffer, Rx_Buffer, sizeof(Tx_Buffer)) == 0)
        {
            printf("\r\n32Mbit串行Flash测试成功!\r\n");
            LED3_ON;
        }
        else
        {
            printf("\r\n32Mbit串行Flash测试失败!\r\n");
            LED1_ON;
        }
        
        
        printf("\r\n测试存储浮点数和整数示例\r\n");
        /* 存储小数和整数的数组，各7个 */
        long double double_buffer[7] = {0};
        int int_buffer[7] = {0};

        /*生成要写入的数据*/
        for (uint8_t k = 0; k < 7; k++)
        {
            double_buffer[k] = k + 0.1;
            int_buffer[k] = k * 500 + 1 ;
        }
        printf("向芯片写入数据：");
        /*打印到串口*/
        printf("\r\n小数 tx = ");
        for (uint8_t k = 0; k < 7; k++)
        {
            printf("%LF, ", double_buffer[k]);
        }
        printf("\r\n整数 tx = ");
        for (uint8_t k = 0; k < 7; k++)
        {
            printf("%d, ", int_buffer[k]);
        }
        
        /* 前面已擦除整个扇区和写入第0页，现继续写入第1页和第2页 */
        /*写入小数数据到第一页*/
        QSPI_Flash_BufferWrite((void *)double_buffer, SPI_FLASH_PageSize * 1, sizeof(double_buffer));
        /*写入整数数据到第二页*/
        QSPI_Flash_BufferWrite((void *)int_buffer, SPI_FLASH_PageSize * 2, sizeof(int_buffer));
        
        /*读取小数数据*/
        QSPI_Flash_BufferRead((void *)double_buffer, SPI_FLASH_PageSize * 1, sizeof(double_buffer));
        /*读取整数数据*/
        QSPI_Flash_BufferRead((void *)int_buffer, SPI_FLASH_PageSize * 2, sizeof(int_buffer));


        printf("\r\n\r\n从芯片读到数据：");
        printf("\r\n小数 rx = ");
        for (uint8_t k = 0; k < 7; k++)
        {
            printf("%LF, ", double_buffer[k]);
        }
        printf("\r\n整数 rx = ");
        for (uint8_t k = 0; k < 7; k++)
        {
            printf("%d, ", int_buffer[k]);
        }
    }
    else
    {
        printf("\tFLASH_ID 错误：0x%X", FlashID);
        LED1_ON;
    }


    while(1);


#if BSP_TZ_SECURE_BUILD
    /* Enter non-secure code */
    R_BSP_NonSecureEnter();
#endif
}

/*******************************************************************************************************************//**
 * This function is called at various points during the startup process.  This implementation uses the event that is
 * called right before main() to set up the pins.
 *
 * @param[in]  event    Where at in the start up process the code is currently at
 **********************************************************************************************************************/
void R_BSP_WarmStart(bsp_warm_start_event_t event)
{
    if (BSP_WARM_START_RESET == event)
    {
#if BSP_FEATURE_FLASH_LP_VERSION != 0

        /* Enable reading from data flash. */
        R_FACI_LP->DFLCTL = 1U;

        /* Would normally have to wait tDSTOP(6us) for data flash recovery. Placing the enable here, before clock and
         * C runtime initialization, should negate the need for a delay since the initialization will typically take more than 6us. */
#endif
    }

    if (BSP_WARM_START_POST_C == event)
    {
        /* C runtime environment and system clocks are setup. */

        /* Configure pins. */
        R_IOPORT_Open (&g_ioport_ctrl, g_ioport.p_cfg);
    }
}

#if BSP_TZ_SECURE_BUILD

BSP_CMSE_NONSECURE_ENTRY void template_nonsecure_callable ();

/* Trustzone Secure Projects require at least one nonsecure callable function in order to build (Remove this if it is not required to build). */
BSP_CMSE_NONSECURE_ENTRY void template_nonsecure_callable ()
{

}
#endif
